package juego;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

import vehiculos.*;
import excepciones.*;


@XmlRootElement
public class Jugador {
	private String nickname;
	private int puntaje;
	private int nivel;
	private int movimientosMaximos;
	private Vehiculo vehiculo;
	private CiudadDeJuego ciudad;
	
	public Jugador() {
		this.nickname = "Player";
	}
	
	public Jugador(String nombre) {
		this.nickname = nombre;
	}
	
	//Asigna un nickname al jugador.
	//Pre: Recibe un string.
	//Post: Se asign� el string recibido como nick.
	@XmlElement
	public void setNickname(String nickname) {
		this.nickname = nickname;
	}
	
	//Devuelve el nickname del jugador.
	public String getNickname() {
		return this.nickname;
	}
	
	//Asigna un puntaje al jugador.
	//Pre: Recibe el entero a asignar como puntaje.
	//Post: Se asign� el puntaje al jugador. 
	@XmlElement
	public void setPuntaje(int puntaje) {
		this.puntaje = puntaje;
	}
	
	//Devuelve el puntaje del jugador.
	public int getPuntaje() {
		return this.puntaje;
	}
	
	@XmlElement
	/*Asigna el nivel jugado al jugador.*/
	public void setNivel(int nivel) {
		this.nivel = nivel;
	}
	
	/* Devuelve el nivel del jugador */
	public int getNivel(){
		return this.nivel;
	}
	
	//Asigna la cantidad de movimientos m�ximos para el veh�culo.
	//Pre: Recibe un n�mero entero.
	//Post: Se asign� la cantidad de movimientos m�ximos.
	@XmlElement
	public void setCantidadDeMovimientosMaximos(int cantidad) {
		this.movimientosMaximos = cantidad;
	}

	//Devuelve la cantidad de movimientos m�ximos del
	//veh�culo.
	public int getCantidadDeMovimientosMaximos() {
		return this.movimientosMaximos;
	}
	
	//Asigna un veh�culo al jugador.
	//Pre: Recibe un veh�culo.
	//Post: Se asign� el veh�culo al jugador.
	@XmlTransient
	public void setVehiculo(Vehiculo unVehiculo) {
		this.vehiculo = unVehiculo;
	}
	
	//Devuelve el veh�culo del jugador.
	public Vehiculo getVehiculo() {
		return this.vehiculo;
	}
	
	//Asigna una ciudad de juego al jugador.
	//Pre: Recibe una ciudad de juego.
	//Post: Se asign� una ciudad de juego al jugador.
	@XmlTransient
	public void setCiudadDeJuego(CiudadDeJuego ciudad){
		this.ciudad = ciudad;
	}
	
	//Devuelve la ciudad de juego del jugador.
	public CiudadDeJuego getCiudadDeJuego() {
		return this.ciudad;
	}
	
	//Actualiza el puntaje del jugador, seg�n la siguiente regla
	//(MovimientosMaximos - CantidadDeMovimientosDelVehiculo) * nivel
	//Pre: El jugador debe tener asignados nivel, cantidad de movimientos
	//m�ximos y un veh�culo.
	//Post: Se actualiz� el puntaje seg�n la regla, se lanza una excepci�n
	//si el puntaje es negativo o cero.
	public void actualizarPuntaje() throws PuntajeMenorACeroException {
                int nivel = this.getNivel();
		int movimientosMaximos = this.getCantidadDeMovimientosMaximos();
		Vehiculo vehiculo = this.getVehiculo();
		int puntaje = (movimientosMaximos - vehiculo.getCantidadDeMovimientos()) * nivel;
		if (puntaje <= 0) throw new PuntajeMenorACeroException();
		this.puntaje = puntaje;
	}

	//Mueve el veh�culo del jugador al norte.
	//Pre: El jugador debe poseer un veh�culo asignado.
	//Post: Se condujo al veh�culo hasta su esquina norte, si es posible
	//circular hasta ella. Se lanza una excepci�n si el puntaje del jugador
	//es negativo o cero.
	public void moverVehiculoAlNorte() throws PuntajeMenorACeroException, MovimientosMaximosAlcanzadosException {
		Vehiculo miVehiculo = this.getVehiculo();
                if (poseeMovimientosRestantes() == false) {
                    throw new MovimientosMaximosAlcanzadosException();
                }

                if (miVehiculo.conducirHastaEsquinaNorte()) {
			try {
				this.actualizarPuntaje();
			} catch (PuntajeMenorACeroException exception) {
				throw exception;
			}
		}
	}
	
	//Mueve el veh�culo del jugador al oeste.
	//Pre: El jugador debe poseer un veh�culo asignado.
	//Post: Se condujo al veh�culo hasta su esquina oeste, si es posible
	//circular hasta ella. Se lanza una excepci�n si el puntaje del jugador
	//es negativo o cero.
	public void moverVehiculoAlOeste() throws PuntajeMenorACeroException, MovimientosMaximosAlcanzadosException {
		Vehiculo miVehiculo = this.getVehiculo();
                if (poseeMovimientosRestantes() == false) {
                    throw new MovimientosMaximosAlcanzadosException();
                }

		if (miVehiculo.conducirHastaEsquinaOeste()) {
			try {
				this.actualizarPuntaje();
			} catch (PuntajeMenorACeroException exception) {
				throw exception;
			}
		}
	}
	
	//Mueve el veh�culo del jugador al sur.
	//Pre: El jugador debe poseer un veh�culo asignado.
	//Post: Se condujo al veh�culo hasta su esquina sur, si es posible
	//circular hasta ella. Se lanza una excepci�n si el puntaje del jugador
	//es negativo o cero.
	public void moverVehiculoAlSur() throws PuntajeMenorACeroException, MovimientosMaximosAlcanzadosException {
		Vehiculo miVehiculo = this.getVehiculo();
                if (poseeMovimientosRestantes() == false) {
                    throw new MovimientosMaximosAlcanzadosException();
                }

		if (miVehiculo.conducirHastaEsquinaSur()) {
			try {
				this.actualizarPuntaje();
			} catch (PuntajeMenorACeroException exception) {
				throw exception;
			}
		}
	}
	
	//Mueve el veh�culo del jugador al este.
	//Pre: El jugador debe poseer un veh�culo asignado.
	//Post: Se condujo al veh�culo hasta su esquina este, si es posible
	//circular hasta ella. Se lanza una excepci�n si el puntaje del jugador
	//es negativo o cero.
	public void moverVehiculoAlEste() throws PuntajeMenorACeroException, MovimientosMaximosAlcanzadosException {
		Vehiculo miVehiculo = this.getVehiculo();
                if (poseeMovimientosRestantes() == false) {
                    throw new MovimientosMaximosAlcanzadosException();
                }

		if (miVehiculo.conducirHastaEsquinaEste()) {
			try {
				this.actualizarPuntaje();
			} catch (PuntajeMenorACeroException exception) {
				throw exception;
			}
		}
	}
        
        // Determina si el jugador ha alcanzado el número máximo de movimientos.
        // Pre: El jugador debe tener un vehículo asignado.
        // Post: Devuelve true si la cantidad de movimientos hechos por el 
        // jugador es menor a la cantidad de movimientos máximos permitidos.
        // Devuelve false en caso contrario.
        public boolean poseeMovimientosRestantes() {
            return (vehiculo.getCantidadDeMovimientos() < movimientosMaximos);
        }
}
